// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 * Description: Liblinux kasan init
 * Author: Huawei OS Kernel Lab
 * Create: Wed Aug 30 10:04:08 2023
 */

#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/init_task.h>
#include <asm/kasan.h>
#include <asm/sections.h>
#include <asm/override.h>

/* task struct memory is not managed by ldk */
void __override __no_sanitize_address kasan_unpoison_task_stack(struct task_struct *task)
{
}

static void __init __no_sanitize_address kernel_kasan_init(void)
{
	int ret;

	unsigned long start = ALIGN_DOWN((unsigned long)kasan_mem_to_shadow(_text), PAGE_SIZE);
	unsigned long end =
		PAGE_ALIGN((unsigned long)kasan_mem_to_shadow(&__liblinux_modules_pool_end[0]));

	BUG_ON(end < start);

	ret = liblinux_pal_reserve_range_name((void *)start, end - start,
			PROT_READ | PROT_WRITE, "[liblinux/kernel-KASAN-SHADOW]");
	if (ret < 0)
		panic("init kasan shadow failed, ret=%d, start=%lx, end = %lx, size=%lx\n",
			ret, start, end, end - start);
}

static void __init __no_sanitize_address kmap_kasan_init(void)
{
	int ret;

	void *start = (void *)(unsigned long)KASAN_SHADOW_START;
	u64 size = KASAN_SHADOW_KMAP_SIZE;

	ret = liblinux_pal_reserve_range_name(start, size,
		PROT_READ | PROT_WRITE, "[liblinux/kmap-KASAN-SHADOW]");
	if (ret < 0)
		panic("init kasan shadow fail, ret=%d, start=%lx, size=%lx\n", ret, start, size);
}

void __init __no_sanitize_address kasan_init(void)
{
	kernel_kasan_init();
	kmap_kasan_init();

	/* At this point kasan is fully initialized. Enable error messages */
	init_task.kasan_depth = 0;
	pr_info("KernelAddressSanitizer initialized\n");
}
